﻿using System;
using agsXMPP.protocol.client;
using agsXMPP.protocol.iq.roster;

namespace ScriptsAPI {
    public static class JFunctions {
        #region Structs
        //Zawara typ wiadomości w oparciu o MessageType
        public static int msgTypeToInt(MessageType x) {
            switch (x) {
                case MessageType.error:
                    return -1;
                case MessageType.chat:
                    return 1;
                case MessageType.groupchat:
                    return 2;
                case MessageType.headline:
                    return 3;
                default:
                    return 0;
            }
        }
        //Zwraca typ wiadomości w oparciu o int
        public static MessageType msgTypeToEnum(int x) {
            switch (x) {
                case -1:
                    return MessageType.error;
                case 1:
                    return MessageType.chat;
                case 2:
                    return MessageType.groupchat;
                case 3:
                    return MessageType.headline;
                default:
                    return MessageType.normal;
            }
        }
        //Zwraca cosinus z liczby $x.
        public static double cos(double x) { return Math.Cos(x); }
        //Zwraca cosinus z liczby $x.
        public static double sin(double x) { return Math.Sin(x); }
        //Zwraca tangens z liczby $x.
        public static double tan(double x) { return Math.Tan(x); }
        //Zwraca cyklometryczny sinus z liczby $x.
        public static double asin(double x) { return Math.Asin(x); }
        //Zwraca cyklometryczny cosinus z liczby $x.
        public static double acos(double x) { return Math.Acos(x); }
        //Zwraca cyklometryczny tangens z liczby $x.
        public static double atan(double x) { return Math.Atan(x); }
        //Zwraca hiperboliczny sinus z liczby $x.
        public static double sinh(double x) { return Math.Sinh(x); }
        //Zwraca hiperboliczny cosinus z liczby $x.
        public static double cosh(double x) { return Math.Cosh(x); }
        //Zwraca hiperboliczny tangens z liczby $x.
        public static double tanh(double x) { return Math.Tanh(x); }
        //Zwraca pierwiastek kwadratowy z liczby $x.
        public static double sqrt(double x) { return Math.Sqrt(x); }
        //Zwraca logarytm naturalny z liczby $x.
        public static double log(int x) { return Math.Log(x); }
        //Zwraca logarytm o podstawie 10 z liczby $x.
        public static double log10(double x) { return Math.Log10(x); }
        //Zamienia zmienną liczbową na zmienną tekstową.
        public static string intToStr(int x) { return x.ToString( ); }
        public static string doubToStr(double x) { return x.ToString( ); }
        //Zamienia zmienną tekstową, jeśli to możliwe, na zmienną liczbową.
        public static int strToInt(string text) { return Convert.ToInt32(text); }
        public static double strToDoub(string text) { return Convert.ToDouble(text); }
        //Podaje długość zmiennej $tekst.
        public static int strLength(string text) { return text.Length; }
        //Zwraca tekst wycięty z $tekst począwszy od $pozycja i o długości $ilość.
        public static string subString(string text, int x, int count) { return text.Substring(x, count); }
        //Zwraca tekst po wycięciu z $tekst ilości znaków $ilość zaczynając wycinanie od $pozycja.
        public static string strDelete(string text, int x, int count) { return text.Remove(x, count); }
        //Zwraca tekst po wstawieniu do $tekst tekstu $sub_tekst zaczynając wstawianie od $pozycja.
        public static string strInsert(string text, string subText, int x) { return text.Insert(x, subText); }
        /**/
        //Zapisuje do pliku $nazwa_pliku linię $linia na pozycji $numer_linii.
        public static bool finsert(string path, string text, int x) { return true; }
        //Zwraca podniesioną do sześcianu liczbę $x.
        public static double cube(double x) { return x * x * x; }
        //Zwraca ludolfinę (stała pi) (pi=3.141592653...).
        public static double pi() { return Math.PI; }
        //Zwraca liczbę Nepera (stała ext) (e=2.718281828...).
        public static double e() { return Math.E; }
        //Zwraca najmniejszą liczbę całkowitą nie mniejszą niż $x.
        public static double celi(double x) { return Math.Round(x, 0, MidpointRounding.AwayFromZero); }
        //Zwraca największą liczbę całkowitą nie większą niż $x.
        public static double floor(double x) { return Math.Round(x, 0, MidpointRounding.ToEven); }
        //Zwraca liczbę Nepera (stała ext) (e=2.718281828...). (->e)
        public static double exp() { return Math.E; }
        //Zwraca wartość bezwzględną z liczby $x.
        public static double abs(double x) { return Math.Abs(x); }
        //Zwraca 10 podniesione do potęgi $x.
        public static double pow10(double x) { return Math.Pow(10, x); }
        //Zwraca pozycję ciągu znaków ansi $sub_text w tekście $tekst.
        public static int strAnsiPos(string text, string subText) { return text.IndexOf(subText); }
        //Zwraca resztę z dzielenia "$x/$y".
        public static double fMod(double x, double y) { return x % y; }
        //Zwraca ułamek $ułamek obcięty do długości $długość.
        public static double setFW(double x, int count) { return Math.Round(x, count); }
        //Zwraca ułamek $ułamek obcięty do długości $długość. (->setfw)
        public static double setFractionWidth(double x, int count) { return Math.Round(x, count); }
        //Zwraca $x * 2^e.
        public static double ldexp(double x) { return x * (2 ^ (int)Math.E); }
        //Zwraca $x podniesione do potęgi $y.
        public static double pow(double x, double y) { return Math.Pow(x, y); }
        //Zwraca 1 (true), jeśli $x jest liczbą.
        public static bool isInt(object xy) {
            try {
                Convert.ToInt32(xy);
                return true;
            } catch {
                return false;
            }
        }
        //Zwraca 1 (true), jeśli $x jest tekstem.
        public static bool isStr(object xy) {
            try {
                Convert.ToString(xy);
                return true;
            } catch {
                return false;
            }
        }
        //Zwraca losową liczbę z przedziału (0, $x-1).
        public static int random(int x) { return random(x); }
        //Zwraca aktualną datę w formacie: dd.mm.yyyy
        public static DateTime date() { return DateTime.Today; }
        //Zwraca aktualny czas w formacie: gg.mm.ss
        public static TimeSpan time() { return DateTime.Now.TimeOfDay; }
        //Zwraca sformatowaną datę, czas wg $format. Uwaga! $format jest zmienną tekstową. Np. "$data = DateTime("dd (dddd) mmmm yyyy");".
        public static DateTime dateTime() { return DateTime.Now; }
        //Zamienia wszystkie duże litery w tekście $tekst na małe i zwraca wynik.
        public static string bigToSmall(string text) { return text.ToLower( ); }
        //Zamienia wszystkie duże litery w tekście $tekst na małe wycinając "ogonki" z polskich znaków i zwraca wynik.
        public static string bigToSmallEx(string text) { return text.ToLowerInvariant( ); }
        //Zamienia wszystkie małe litery w tekście $a na duże i zwraca wynik.
        public static string smallToBig(string text) { return text.ToUpper( ); }
        //Zamienia wszystkie małe litery w tekście $tekst na duże wycinając "ogonki" z polskich znaków i zwraca wynik.
        public static string smallToBigEx(string text) { return text.ToUpperInvariant( ); }
        //Zwraca tekst $tekst po obcięciu do długości $długość.
        public static string strSetLength(string text, int x) { return text.Remove(x + 1); }
        //Zwraca pozycję tekstu $sub_tekst w tekście $tekst.
        public static int strPos(string text, string subText) { return text.IndexOf(subText); }
        //Zwraca tekst wypełniony znakiem $znak $ilość razy.
        public static string stringOfChar(char ch, int x) { return "".PadLeft(x, ch); }
        /**/
        //Porównuje $długość początkowych znaków 2 zmiennych tekstowych i zwraca 0 jeśli są równe.
        public static bool strncmp(string text1, string text2) { return true; }
        //Zwraca ilość dni, które upłynęły od początku n.e. do $rok.$miesiac.$dzien.
        public static double EncodeDate(DateTime data) { return data.Date.ToOADate( ); }
        //Zwraca loczbę sekund. Np. 546
        public static double EncodeTime(DateTime time) { return time.TimeOfDay.TotalSeconds; }
        /**/
        //Rozwiązuje (i zwraca wynik) ciąg liczb. Można używać nawiasów oraz funkcji matematycznych dostępnych w języku skryptowym. Np. "$wynik = solve("3*(2+2)");".
        /*public static double solve(string text) { }*/
        /**/
        //Zamienia zmienną tekstową zawierającą liczbę w hex'ach, na zmienną liczbową.
        public static int HexStrToInt(string hex) { return Convert.ToInt32(hex); }
        /**/
        //Zamienia zmienną liczbową na zmienną tekstową zawerającą liczbę w postaci hex.
        public static string IntToHexStr(int x) { return x.ToString( ); }
        /**/
        //Formatuje tekst $tekst ze znakami specjalnymi wg użytkownika $numer_gg. (->fstr)
        /*public static string format_str(string jid, string text) { }*/
        /**/
        //Formatuje tekst $tekst ze znakami specjalnymi wg użytkownika $numer_gg.
        /*public static string fstr(string jid, string text) { }*/
        /**/
        //Zwraca znak ASCII o podanym kodzie.
        /*public static char getChar(int x) { }*/
        /**/
        //Zwraca kod podanego znaku ASCII.
        /*public static int getInt(char ch) { }*/
        /**/
        //Wycina z tekstu $tekst wszystkie znaki, które nie są literami.
        /*public static string StrCutAll(string text) { }*/
        #endregion
        #region XMPP & Temp
        public static int getSubscrInt(this SubscriptionType subscription) {
            if (subscription == SubscriptionType.both)
                return 0;
            else if (subscription == SubscriptionType.to)
                return 7;
            else if (subscription == SubscriptionType.from)
                return 14;
            else
                return 21;
        }
        public static int getStatusInt(this Presence presence) {
            if (presence.Show.ToString( ) != "NONE")
                return Array.IndexOf(Const.statuses, presence.Show.ToString( ));
            else {
                if (presence.Type.ToString( ) == "available")
                    return 1;
                else if (presence.Type.ToString( ) == "invisible")
                    return 6;
                else
                    return 0;
            }
        }
		public static string getDescStr(this Presence presence) {
			if (presence.Show.ToString( ) != "NONE")
				return presence.Show.ToString( );
            else
				return presence.Type.ToString( );
        }
        public static string getStatusStr(int num) {
            if (num > 0 && num < Const.statuses.Length)
                return Const.statuses[num];
            else
                return Const.statuses[0];
        }
        public static string getStatusStr(this Presence status_info) {
            if (status_info != null)
                return status_info.Type.ToString( );
            else
                return Const.statuses[0];
        }
        public static int getStatusInt(string status) {
            if (Array.IndexOf(Const.statuses, status) > 0)
                return Array.IndexOf(Const.statuses, status);
            else
                return 0;
        }
        public static Presence getStatusPre(string status) {
            Presence p = new Presence( );
            int num = 0;
            if (Array.IndexOf(Const.statuses, status) > 0)
                num= Array.IndexOf(Const.statuses, status);
            switch (num) {
                case 1:
                    p.Type = PresenceType.available;
                    p.Show = ShowType.NONE;
                    break;
                case 2:
                    p.Type = PresenceType.available;
                    p.Show = ShowType.chat;
                    break;
                case 3:
                    p.Type = PresenceType.available;
                    p.Show = ShowType.away;
                    break;
                case 4:
                    p.Type = PresenceType.available;
                    p.Show = ShowType.xa;
                    break;
                case 5:
                    p.Type = PresenceType.available;
                    p.Show = ShowType.dnd;
                    break;
                case 6:
                    p.Type = PresenceType.invisible;
                    p.Show = ShowType.NONE;
                    break;
                default:
                    p.Type = PresenceType.unavailable;
                    p.Show = ShowType.NONE;
                    break;
            }
            return p;
        }        
        public static Presence getStatusPre(int num) {
            Presence p = new Presence( );
            switch (num) {
                case 1:
                    p.Type = PresenceType.available;
                    p.Show = ShowType.NONE;
                    break;
                case 2:
                    p.Type = PresenceType.available;
                    p.Show = ShowType.chat;
                    break;
                case 3:
                    p.Type = PresenceType.available;
                    p.Show = ShowType.away;
                    break;
                case 4:
                    p.Type = PresenceType.available;
                    p.Show = ShowType.xa;
                    break;
                case 5:
                    p.Type = PresenceType.available;
                    p.Show = ShowType.dnd;
                    break;
                case 6:
                    p.Type = PresenceType.invisible;
                    p.Show = ShowType.NONE;
                    break;
                default:
                    p.Type = PresenceType.unavailable;
                    p.Show = ShowType.NONE;
                    break;
            }
            return p;
        }        

        #endregion
        #region Bot
        /*
        //Ustawia poziom logowania zdarzeń.
        public static void setLogLevel(int x) { }
        //Ustawia nowy opis, który ustawi bot, gdy będzie się wyłączał.
        public static void setJbotExitDescr(string text) { }
        //Ustawia jedną z 4 ($variable_no: 0-3) zmiennych użytkownika o numerze $user_no na true lub false.
        public static void setUserVariable(int x) { }
        //Ustawia nowy opis statusu bota.
        public static void setDescr(string text) { }
        //Ustawia nowy, stały opis statusu bota (gdy $opis_wejściowy = "no", włącza domyślny status).
        public static void setJbotLoginDescr(string text) { }
        //Zwraca uin bota.
        public static string jbotJid() { }
        //Zwraca opis statusu, z którym zalogował się bot.
        public static string jbotLoginDescr() { }
        //Zwraca aktualny opis statusu bota.
        public static string jbotDescr() { }
        //Zwraca Imię bota.
        public static string jbotName() { }
        //Zwraca uin admina bota.
        public static string adminJid() { }
        //Zwraca opis statusu, który ustawi bot, gdy będzie się wyłączał.
        public static string jbotExitDescr() { }
        //Zwraca pełną nazwę pliku, do którego loguje bot (łącznie ze ścieżką dostępu).
        public static string logFile() { }
        //Zwraca poziom logowania.
        public static int logLevel() { }
        //Zwraca ilość linii w logu ekranowym.
        public static int logLines() { }
        //Zwraca ilość użytkowników.
        public static int jbotUserNo() { }
        //Zwraca ilość użytkowników rozpoznawanych jako Master.
        public static int jbotMasterNo() { }
        //Wyłącza bota.
        public static void terminate() { }
        //Zwraca liczbę godzin z uptime.
        public static int uptimeH() { }
        //Zwraca liczbę minut z uptime.
        public static int uptimeM() { }
        //Usypia bota.
        public static void sleep() { }
        //Budzi bota po użyciu sleep().
        public static void awake() { }
        //Zwraca ścieżkę dostępu, z której został uruchomiony bot.
        public static string path() { }
        //Zwraca numer linii $nr_linii z logu bota.
        public static string getLogLine(int x) { }
        //Dodaje do listy kontaktów użytkownika o numerze $numer_gg.
        public static void addUser(string text) { }
        //Usuwa z listy kontaktów użytkownika o numerze $numer_gg.
        public static void delUser(string text) { }
        //Zwraca uptime bota w postaci gg:mm.
        public static DateTime uptime() { }
        //Ustala nowy czas przerwania dla skryptu wykonywanego co pewien, ustalony czas. Minimalny interwał: 5000.
        public static void SetLoopInterval(int x) { }
        //Ustawia plik ze skryptem, który ma być wykonywany co pewien czas. Jeśli za nazwe pliku podamy "no" wykonywanie skryptu zostanie zatrzymane.
        public static void SetLoopScript(string text) { }
        //Wywołuje zamknięcie programu.
        public static void jbotClose() { }
        //Zwraca 1 (true) jeśli aktualny $uin prowadzi z nami rozmowę.
        public static bool isTalking() { }
        //Zwraca 1 (true) jeśli bot jest w trybie uśpionym.
        public static bool isSleepMode() { }
        //Zwraca 1 (true) jeśli bot ma ustawiony reconnect.
        public static bool isReconnect() { }
        //Zwraca maksymalną ilość użytkowników bota.
        public static int jbotMaxUsers() { }
        //Zwraca 1 (true) jeśli bot jest połączony z serwerem gg.
        public static bool isJbotOnline() { }
        //Ustawia reconnect na 1 (true) lub 0 (false); włączony/wyłączony.
        public static void set_reconnect(bool set) { }
        //Rozłącza i ponownie łączy bota.
        public static void reconnect() { }
        */
        #endregion
        #region User
        /*
        //Zwraca numer gg użytkownika o pozycji $pozycja.
        public static string userJid(int x) { }
        //Zwraca pozycję użytkownika o numerze gg $numer_gg (-1, gdy użytkownik nie istnieje).
        public static int userNo(string text) { }
        //Zwraca aktualny opis ze statusu użytkownika $numer_gg.
        public static string userDescr(string text) { }
        //Zwraca 1 (true), gdy numer $numer_gg ma prawa Mastera.
        public static bool isMaster(string text) { }
        //Zwraca 1 (true), gdy numer $numer_gg jest zablokowany.
        public static bool isBlocked(string text) { }
        //Zwraca imię dla $numer_gg.
        public static string userName(string text) { }
        //Zwraca welcome dla $numer_gg.
        public static string userWelcome(string text) { }
        //Zwraca 1 (true), gdy użytkownik $numer_gg istnieje.
        public static bool isUser(string text) { }
        //Zwraca pozycję Mastera o numerze gg $numer_gg (-1, gdy użytkownik nie istnieje lub nie jest Masterem).
        public static int masterNo(string text) { }
        //Zwraca numer gg Mastera o pozycji $pozycja.
        public static string masterJid(int x) { }
        //Zwraca aktualny status użytkownika $numer_gg.
        public static int userStatus(string text) { }
        //Zwraca 1 (true) jeśli $adres_email jest poprawnym adresem e-mail.
        public static bool isMailAddr(string text) { }
        //Zwraca informację seen dla podanego $numer_gg ($tryb: 0-1).
        public static string[ ] seen(string jid) { }
        //Ustawia nowe imię/ksywke $nowe_imie dla użytkownika o numerze gg $numer_gg.
        public static void setUserName(string jid, string nickname) { }
        //Ustawia nowe powitanie $nowe_powitanie dla użytkownika o numerze gg $numer_gg.
        public static void setUserWelcome(string jid, string welcome) { }
        //Ustawia jedną z 4 ($variable_no: 0-3) zmiennych użytkownika o numerze $user_no na true lub false
        public static void userVariable(string jid, int x) { }
        */
        #endregion
        #region Scripts
        /*
        //Uruchamia skrypt GGBot'a o nazwie $nazwa_pliku. Zwraca to, co zwróci uruchomiony skrypt.
        public static bool executeScript(string path) { }
        //Zapisuje zmienną $nazwa_zmiennej do pliku, pod sesją $sesja. Uwaga zmienna musi być w " "!
        public static bool saveVariable(object var, string session) { }
        //Wczytuje zmienną $nazwa_zmiennej z pliku, która została zapisana w sesji $sesja. Uwaga zmienna musi być w " "!
        public static object loadVariable(string session) { }
        //Usuwa zmienną $nazwa_zmiennej z pliku, która została zapisana w sesji $sesja. Uwaga zmienna musi być w " "!
        public static bool delVariable(string session) { }
        //Ustawia skrypt GGBot'a $nazwa_pliku, aby uruchamiał się zawsze o godzinie $godzina, minut $minuta. Zmienne $godzina i $minuta, to liczby.
        public static void ExecuteScriptAt(string path, DateTime time) { }
        //Ustawia plik ze skryptem dla pdreply. Jeśli za nazwe pliku podamy "no", skrypt nie bedzie wykonywany.
        public static void SetPdreplyScript(string path) { }
        //Zwraca numer akcji, która wywołała skrypt.
        public static int action() { }
        //Zwraca ścieżkę dostępu z jakiej został uruchomiony skrypt.
        public static string scriptPath() { }
        //Zwraca nazwę skryptu.
        public static string scriptName() { }
        */
        #endregion
        #region Packets
        /*
        //Zwraca numer użytkownika, który wywołał skrypt.
        public static string senderJid() { }
        //Zwraca treść ostatniej wiadomości użytkownika, który wywołał skrypt.
        public static string recvMessage() { }
        //Zwraca treść przedostatniej wiadomości użytkownika, który wywołał skrypt.
        public static string recvMessage2() { }
        //Wysyła wiadomość o treści $wiadomość do numeru, który wywołał skrypt.
        public static bool msgToSender(string msg) { }
        //Wysyła sformatowaną wiadomość o treści $wiadomość do numeru, który wywołał skrypt. (->fmsg_to_sender)
        public static bool formatedMsgToSender(string msg) { }
        //Wysyła sformatowaną wiadomość o treści $wiadomość do numeru, który wywołał skrypt.
        public static bool fmsgToSender(string msg) { }
        //Wysyła wiadomość o treści $wiadomość do numeru $numer_gg.
        public static void msg(string jid, string msg) { }
        //Wysyła sformatowaną wiadomość o treści $wiadomość do numeru $numer_gg.
        public static void fmsg(string jid, string msg) { }
        //Wysyła sformatowaną wiadomość o treści $wiadomość do numeru $numer_gg. (->fmsg)
        public static void formatedMsg(string jid, string msg) { }
        //Kolejkuje nową wiadomość do wysłania (wiadomość czeka w kolejce max. 60 sek.) o treści $treść, temacie $stemat, od $od, do $do.
        public static void queueMail(string to, string from, string thared, string body) { }
        //Zwraca wiadomość, która ma być wysłana do sender_uin (tylko w sendmsg).
        public static string sendMessage(string jid) { }
        //Ustawia nową wiadomość do wysłania (tylko w sendmsg).
        public static void setSendMessage(string jid, string text) { }
        //Ustawia nową treść $wiadomość odebranej wiadomości dla $uin.
        public static void setMgRecvMsg(string text) { }
        //(->set_mg_recv_msg)
        public static void setMgr(string text) { }
        //Zwrca czas nadejścia wiadomości w sekundach od 1970.01.01 (UTC).
        public static DateTime recvTime() { }
        //Wysyła listę kontaktów do użytkownika $uin.
        public static void sendUserList(string jid) { }
        //Rozpoczyna czat użytkownika $numer_gg1 z użytkownikiem $numer_gg2.
        public static void chatWith(string jid1, string jid2) { }
        //Sprawdza, czy można rozpocząć czat z użytkownikiem $numer_gg.
        public static bool isChatFree(string jid) { }
        */
        #endregion
        #region Roster
        /*
        //Wysyła zapytanie $zapytanie do katalogu publicznego o typie $typ i numerze sekwencyjnym $seq.
        public static void queuePdrequest(string request, string type, int seq) { }
        */
        #endregion
        #region Windows
        /*
        //Wyświetla w logu bota tekst $tekst.
        public static bool echo(string text) { }
        //Odgrywa plik dźwiękowy $nazwa_pliku. Obsługiwane typy zależą wyłącznie od zainstalowanych kodeków w systemie.
        public static bool PlaySound(string path) { }
        //Wyświetla MessageBox o tytule $tytuł i tekście $tekst.
        public static void messageBox(string title, string text) { }
        //Wyświetla MessageBox o tytule $tytuł i tekście $tekst.
        public static void msgbox(string title, string text) { }
        //Wyświetla okno wprowadzania danych (o tytule $tytuł i treści $tekst) z początkową wartością $wartość.
        public static void InputQuery(string title, string body, string defaults) { }
        */
        #endregion
    }
}